package parser;
import java.util.*;
import java.io.*; 
import antlr.RecognitionException;

public class FunctionScope2 extends Scope2 {
    
    FunctionScope2(List<Parameter2> parameters, Scope2 enclosing) {
        super();
        // Is function name in the scope of the function?
        this.enclosing = enclosing;
        indices = new HashMap<Integer, Integer>();
        locals = new BitSet();
        globals = new BitSet();
        Set<Integer> pNames = new HashSet<Integer>();
        for (Parameter2 p : parameters) {
            if (pNames.contains(p.getName()))
                throw new Error("Repeat name " + p.getName());
            indices.put(p.getName(), indices.size());
            locals.set(p.getName());
            pNames.add(p.getName());
        }
    }
    
    Scope2 enclosing;
    BitSet locals;
    BitSet globals;
    Map<Integer, Integer> indices;
    int tempIndex;
     
    Expr name(int name) {
        return new Variable(name, this);
    }
 

    void global(int name) {
        globals.set(name);
        locals.clear(name);
    }
    
    void bind(int name) {
        locals.set(name, !globals.get(name));
    }
    
    Integer getIndex(int name) {
        return indices.get(name); 
    }
             
    Scope2 beginFunction(List<Parameter2> parameters) {
        throw new Error("Nested functions not supported");
    }
    
    Scope2 beginClass(int name) {
        throw new Error("Nested classes not supported");
    }

    boolean closed;
    
    int[] getLocals() {
        if (!closed)
            throw new Error("Illegal State");
        int size = locals.cardinality();
        int[] names = new int[size];
        for(int i= locals.nextSetBit(0); i>=0; i=locals.nextSetBit(i+1)) {
            names[indices.get(i)] = i;
        }
        return names;
    }
    
    Scope2 close() {
        closed = true;
        for(int i= locals.nextSetBit(0); i>=0; i=locals.nextSetBit(i+1)) {
            if (!indices.containsKey(i)) {
                indices.put(i, indices.size());
            }
        }
        return enclosing;
    }
     
    
    
 
}
